package com.study.service.impl;

import com.study.bean.Menu;
import com.study.bean.MenuStream;
import com.study.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MenuServiceImpl implements MenuService {

    @Resource
    JdbcTemplate jtemplate;

    @Override
    public Menu getMenu() {
        return null;
    }

    @Override
    public void updateMenu(Long id, String name) {


    }


    /**
     * 每一个缓存数据都来指定要放到哪个名字的缓冲【指定缓存分区】
     * Cacheable({"cahce:menu", "mu"})//代表 当前方法的结果需要缓存，如果缓存中有，方法不调用，如果缓存中没有，查询后彷如缓存
     * <br>
     * <p>
     * 3默认行为
     * 3.1 如果有，方法不用调用
     * 3.2 key默认自动生成 ，缓存名字::SimpleKey []
     * 3.3 缓存value 默认jdk序列化 机制
     * 3.4 默认过期时间 -1
     * <p>
     * 4 自定义
     * 4.1 指定生成的缓存使用key:key属性 指定，接受一个SpEL ，如果要用字符串，需要单引号
     * 4.2 缓存时间|配置文件spring.cache.redis.time-to-live
     * 4.3 指定JSON格式
     */
    //@Cacheable(value = {"cahce:menu", "mu"}, key = "'sysMenu'", sync = true)//|https://cloud.tencent.com/developer/article/1497596
//代表 当前方法的结果需要缓存，如果缓存中有，方法不调用，如果缓存中没有，查询后彷如缓存
    @Cacheable(value = {"cahce:menu"}, key = "'sysMenu'", sync = true)//使用  sync 缓存名字只能有1个
    @Override
    public List<MenuStream> getAllwithJ8Stream() {
        log.info("menu with java8stream  by  mysql db");
        // 使用java8 stream 封装父子关系，来展示 ztree 标准JSON格式
        List<MenuStream> queryForList = jtemplate.query("select id,pId ,name,url,icon from t_menu", new BeanPropertyRowMapper(MenuStream.class));

        // 获取取根节点
        List<MenuStream> collect = queryForList.stream().filter((menu) -> {
            return menu.getPid() == null;
        }).map((menu) -> {
            menu.setChildren(getChildren(menu, queryForList));
            return menu;
        }).sorted((m1, m2) -> {
            return m1.getId() - m2.getId();
        }).collect(Collectors.toList());
        System.out.println(collect);
        return collect;
    }

    /**
     * 清除缓存
     */
    //1 @CacheEvict(value = {"cahce:menu", "mu"}, key = "'sysMenu'")
   /* 2 @Caching(evict = {
            @CacheEvict(value = "cahce:menu", key = "'sysMenu'"),
            @CacheEvict(value = "mu", key = "'sysMenu'")
    })*/
    @CacheEvict(value = "cahce:menu", allEntries = true)//cahce:menu::sysMenu|删除 指定分区下的 缓存，不
    //@CachePut//双写模式
    @Override
    @Transactional
    public void menuDelcache() {
        log.info("menuDelcache");
    }

    /**
     * 查找所有节点子节点
     *
     * @param root
     * @param all
     * @return
     */
    private List<MenuStream> getChildren(MenuStream root, List<MenuStream> all) {
        List<MenuStream> collect = all.stream().filter(menu -> {
            // 根据父节点查找子节点
            return menu.getPid() == root.getId();
        }).map(menuStream -> {
            // 递归设置 子节点
            List<MenuStream> children = getChildren(menuStream, all);
            menuStream.setChildren(children);
            if (children != null && !children.isEmpty()) {//已经使用了注解，此处 有点多余，如果没使用注解用此处方法设置
                // @JsonInclude(JsonInclude.Include.NON_EMPTY) // 设置不为空的时候返回
                // private List<MenuStream> children;
            }
            return menuStream;
        }).collect(Collectors.toList());
        return collect;
    }
}
